package model.objects;

import java.awt.Graphics;
import java.awt.image.BufferedImage;

import javax.swing.JPanel;

import model.general.Location;
import model.general.Util;
import model.move.IMove;
import model.move.MoveBoat;
import model.observer.Obsever;
import model.observer.Obseverable;

public class Boat extends Sprites implements IAnimateMainActor, Obseverable {

	private IAnimateSubActor hook;
	private boolean isMoveLeft = false;
	private int life = Util.LIFE, score = 0,
			speed = Util.DEFAULT_SPEED_MOVE_BOAT;
	private long time1, time2;
	private boolean isFast = false;

	private Obsever view;

	private static Boat boat = null;

	private static BufferedImage DEFAUT_IMG_BOAT_LEFT;
	private static BufferedImage DEFAUT_IMG_BOAT_RIGHT;

	public static Boat getInstance() {
		if (boat == null) {
			String[] imgBoat = {Util.BOAT_IMG_LEFT,Util.BOAT_IMG_RIGHT,Util.BOAT_IMG_RIGHT};
			boat = new Boat(new Location(0, 80),imgBoat);
		}
		return boat;

	}

	private Boat(Location location, String[] srcImg) {
		super(location, srcImg);
		this.move = new MoveBoat(location);
		DEFAUT_IMG_BOAT_LEFT = loadImage.getbufferImage(srcImgLeft);
		DEFAUT_IMG_BOAT_RIGHT = loadImage.getbufferImage(srcImgRight);
		this.hook = Hook.getInstance();
		this.hook.setBoat(this);

		// addObsever((Obsever) pnl);???
	}

	@Override
	public void show(Graphics g) {
		g.drawImage(img, location.getX(), location.getY(), null);
		hook.show(g);
	}

	@Override
	public void moveHook() {
		new Thread(new Runnable() {
			@Override
			public void run() {
				if (!hook.getState()) {
					hook.setIsMove(true);
					hook.move();
				}
			}
		}).start();

	}

	@Override
	public void moveLeft() {
		checkMoveFast();
		if (!hasOutPanel()) {
			isMoveLeft = true;
			isChangeImage();
			move.moveLeft();
			hook.updateLocation(location);
		}

	}

	@Override
	public void moveRight() {
		checkMoveFast();
		if (!hasOutPanel()) {
			isMoveLeft = false;
			isChangeImage();
			move.moveRight();
			hook.updateLocation(location);
		}

	}

	@Override
	public IAnimateSubActor getHook() {
		return this.hook;
	}

	public void addLife(int add) {
		this.life += add;
		notifyObsever();
	}

	public void addScore(int add) {
		this.score += add;
		notifyObsever();
	}

	public void updateSpeed(int step) {
		this.speed = step;
		time1 = System.currentTimeMillis();
		isFast = true;
		move.setSpeed(step);
		notifyObsever();
	}

	private void checkMoveFast() {
		if (isFast) {
			time2 = System.currentTimeMillis();
			if ((time2 - time1) >= Util.DEFAULT_TIME_FAST_SPEED) {
				this.speed = Util.DEFAULT_SPEED_MOVE_BOAT;
				move.setSpeed(speed);
				time1 = time2 = 0;
				isFast = false;
			}
		}
	}

	public int getWidth() {
		return width;
	}

	public int getHeight() {
		return height;
	}

	public boolean hasOutPanel() {

		int min = minX;
		int max = maxX - this.width;
		if ((location.getX() < min)) {
			this.location.setX(min);
			return true;
		}
		if ((location.getX() > max)) {
			this.location.setX(max);
			return true;
		}
		return false;
	}

	private void isChangeImage() {
		// TODO Auto-generated method stub
		if (isMoveLeft == true) {
			img = DEFAUT_IMG_BOAT_LEFT;
		}
		if (isMoveLeft == false) {
			img = DEFAUT_IMG_BOAT_RIGHT;
		}
	}

	public Location getLocation() {
		return location;
	}

	@Override
	public Obseverable getObserableHook() {
		// TODO Auto-generated method stub
		if (this.hook instanceof Obseverable)
			return (Obseverable) this.hook;
		return null;
	}

	public int getLife() {
		return this.life;
	}

	public void setLife(int life) {
		this.life = life;
	}

	public int getScore() {
		return this.score;
	}

	public void setScore(int score) {
		this.score = score;
	}

	/**
	 * add observer VIEW
	 */
	@Override
	public void addObsever(Obsever obsever) {
		view = obsever;
	}

	/**
	 * when option of boat is change, notify to the VIEW
	 */
	@Override
	public void notifyObsever() {
		if (view != null) {
			view.check();
		}
	}

	/**
	 * remove observer VIEW
	 */
	@Override
	public void removeObsever(Obsever obsever) {
		view = null;
	}

	public int getSpeed() {
		return speed;
	}

	public void setSpeed(int speed) {
		this.speed = speed;

	}

	@Override
	public void setHook(Hook hook) {
		hook.setBoat(this);
		this.hook = hook;
	}

}
